package com.ifacebox.web.admin.upload.controller;

import com.ifacebox.web.admin.controller.BaseBodyController;
import com.ifacebox.web.admin.upload.model.Upload;
import com.ifacebox.web.common.annotation.UserAgentRequest;
import com.ifacebox.web.common.client.OssClient;
import com.ifacebox.web.common.model.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
import org.springframework.stereotype.Controller;
import org.springframework.util.unit.DataSize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.UUID;

/**
 * @author znn
 */
@ControllerAdvice
@Controller
public class UploadOssController extends BaseBodyController {
    @Resource
    private UploadProperties uploadProperties;
    @Resource
    private OssClient ossClient;

    @PostMapping("/admin/oss/upload")
    @ResponseBody
    public ModelResponse<Upload> upload(@UserAgentRequest UserAgent userAgent, HttpServletRequest request, MultipartFile file, String bucketName) {
        try {
            if (!uploadProperties.getExtension().contains(FilenameUtils.getExtension(file.getOriginalFilename()))) {
                return new ModelResponse<>(StatusResponse.EXCEPTION, String.format("上传文件中包含不支持的格式！(%s)", uploadProperties.getExtension()));
            }
            String fileName = String.format("%s/%s.%s"
                    , String.format("%tY/%tm/%td", new Date(), new Date(), new Date())
                    , UUID.randomUUID().toString(), FilenameUtils.getExtension(file.getOriginalFilename()));
            FileUtils.forceMkdirParent(new File(uploadProperties.getLocation(), fileName));
            String fileSrcUrl = String.format("%s/admin/oss/download?fileName=%s", request.getContextPath(), fileName);
            String fileOssUrl = ossClient.transferTo(file, bucketName, fileName);
            traceLoggerService.addTraceLogger(userAgent, "上传文件 - {}/{} SRC - {} OSS - {}", uploadProperties.getLocation(), fileName, fileSrcUrl, fileOssUrl);
            return new ModelResponse<>(StatusResponse.SUCCESS, new Upload(fileName, fileSrcUrl, fileOssUrl));
        } catch (IOException e) {
            return new ModelResponse<>(StatusResponse.EXCEPTION, String.format("上传文件失败！(%s)", e.getMessage()));
        }
    }

    @GetMapping("/admin/oss/download")
    public void download(HttpServletResponse response, String fileName) throws IOException {
        File file = new File(uploadProperties.getLocation(), fileName);
        response.setHeader("Content-Type", "application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(file.getName(), "UTF-8"));
        response.setContentType("application/octet-stream");
        FileUtils.copyFile(file, response.getOutputStream());
    }

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    @ResponseBody
    public BaseResponse maxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        if (e.getCause().getCause() instanceof SizeLimitExceededException) {
            return new BaseResponse(StatusResponse.EXCEPTION, String.format("上传文件大小(%dMB)超出限制！(%dMB)"
                    , DataSize.ofBytes(((SizeLimitExceededException) e.getCause().getCause()).getActualSize()).toMegabytes()
                    , DataSize.ofBytes(((SizeLimitExceededException) e.getCause().getCause()).getPermittedSize()).toMegabytes()));
        }
        return new BaseResponse(StatusResponse.EXCEPTION, String.format("上传文件大小超出限制！(%dMB~%dMB)"
                , uploadProperties.getMaxFileSize().toMegabytes()
                , uploadProperties.getMaxRequestSize().toMegabytes()));
    }
}
